package gui.mainFrame.testConditionViewer.branchViewer;

import gui.mainFrame.testConditionViewer.branchViewer.GraphPanel.ListenableDirectedMultigraph;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import org.jgraph.graph.AttributeMap;
import org.jgraph.graph.DefaultGraphCell;
import org.jgraph.graph.GraphConstants;
import org.jgrapht.ext.JGraphModelAdapter;
import org.jgrapht.graph.DefaultEdge;
import testGenerator.Controller;
import testGenerator.testMethodModel.AutoJUnitMethod;
import testGenerator.testMethodModel.TestCondition;
import testGenerator.testMethodModel.TestPath;

/**
 *
 * @author William Whitney
 */
public class BranchGraphManipulator
{

    private final ArrayList<TestPath> testBranches;
    private final JGraphModelAdapter<String, org.jgrapht.graph.DefaultEdge> jgAdapter;
    private final ListenableDirectedMultigraph<String, DefaultEdge> g;

    public BranchGraphManipulator(ListenableDirectedMultigraph<String, org.jgrapht.graph.DefaultEdge> g, JGraphModelAdapter<String, org.jgrapht.graph.DefaultEdge> jgAdapter, Controller controller)
    {
        this.g = g;
        this.jgAdapter = jgAdapter;
        AutoJUnitMethod currMethod = controller.getCurrMethod();
        testBranches = currMethod.testBranches;

        buildView();
    }

    private void buildView()
    {
        //Add each condition from all columns to their own list
        ArrayList<CondColumn> condColumns = buildCondColumns();

        //Make each column have only unique entries
        makeCondColumnsUnique(condColumns);

        //Add to view
        addColumnsToView(condColumns);

        //Draw Edges
        drawEdges(testBranches);

    }

    private void makeCondColumnsUnique(ArrayList<CondColumn> condColumns)
    {
        for (CondColumn col : condColumns)
        {
            col.makeUnique();
        }
    }

    private ArrayList<CondColumn> buildCondColumns()
    {
        ArrayList<CondColumn> condColumns = new ArrayList<CondColumn>();
        for (TestPath path : testBranches)
        {
            for (int i = 0; i < path.conditions.size(); i++)
            {
                CondColumn currCondColumn;
                if (condColumns.size() - 1 < i)
                {
                    condColumns.add(new CondColumn());
                }
                currCondColumn = condColumns.get(i);

                currCondColumn.getConds().add(path.conditions.get(i));
            }
        }
        return condColumns;
    }

    private void addColumnsToView(ArrayList<CondColumn> condColumns)
    {

        for (int guiRowPosition = 0; guiRowPosition < condColumns.size(); guiRowPosition++)
        {
            CondColumn columnValues = condColumns.get(guiRowPosition);

            for (int guiColPosition = 0; guiColPosition < columnValues.getConds().size(); guiColPosition++)
            {
                TestCondition currTestCond = columnValues.getConds().get(guiColPosition);

                String vertex = currTestCond.getCondition();
                g.addVertex(vertex);

                positionVertexAt(vertex, guiColPosition * 200, guiRowPosition * 100);


            }

        }
    }

    private void positionVertexAt(Object vertex, int x, int y)
    {
        DefaultGraphCell cell = jgAdapter.getVertexCell(vertex);
        AttributeMap attr = cell.getAttributes();
        Rectangle2D bounds = GraphConstants.getBounds(attr);

        Rectangle2D newBounds =
                new Rectangle2D.Double(
                x,
                y,
                bounds.getWidth() + 50,
                bounds.getHeight());

        GraphConstants.setBounds(attr, newBounds);



        // TODO: Clean up generics once JGraph goes generic
        AttributeMap cellAttr = new AttributeMap();
        cellAttr.put(cell, attr);
        jgAdapter.edit(cellAttr, null, null, null);
    }

    private void drawEdges(ArrayList<TestPath> testBranches)
    {
        for (TestPath path : testBranches)
        {
            TestCondition lastCond = null;
            for (TestCondition cond : path.conditions)
            {
                if (lastCond != null)
                {
                    g.addEdge(lastCond.getCondition(), cond.getCondition(), new MyEdge(lastCond.getCondition(),cond.getCondition()));
         

                }
                lastCond = cond;
            }
        }
    }

  
}
